package cn.kailangtu.serialutils;

import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class HexUtil {
    /*
     *
     * */
    public static String bytesToHexString(byte[] bytes) {
        String result = "";
        for (int i = 0; i < bytes.length; i++) {
            String hexString = Integer.toHexString(bytes[i] & 0xFF);
            if (hexString.length() == 1) {
                hexString = '0' + hexString;
            }
            result = result + hexString.toUpperCase();
        }
        return result;
    }



    /*
     * 十六进制byte数组转成字符串
     * */
    public static String get十六进制byte数组转成字符串(byte[] bytes) {
        String result = "";
        for (int i = 0; i < bytes.length; i++) {
            String hexString = Integer.toHexString(bytes[i] & 0xFF);
            if (hexString.length() == 1) {
                hexString = '0' + hexString;
            }
            result = result + hexString.toUpperCase();
        }
        return result;
    }

    /**
     * 把16进制字符串转换成字节数组
     * @param hex
     * @return byte[]
     */
    public static byte[] get十六进制字符串转成byte数组(String hex) {
        hex = hex.toUpperCase();
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }
    private static int toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    public static String getInt类型转成十六进制字符串(int no) {
        String str = Integer.toHexString(no);
        return str;
    }
    public static String getLong类型转成十六进制字符串(long no) {
        String str = Long.toHexString(no);
        return str;
    }
    public static String getDouble类型转成十六进制字符串(double no) {
        String str = Double.toHexString(no);
        return str;
    }

    public static int get十六进制字符串转成Int类型(String hex) {
        BigInteger bi = new BigInteger(hex, 16);
        int no = bi.intValue();
        return no;
    }
    public static long get十六进制字符串转成Long类型(String str) {
        long no = Long.parseLong(str, 16);
        return no;
    }

    public static int get二进制字符串转成Int类型(String hex) {
        BigInteger bi = new BigInteger(hex, 2);
        int no = bi.intValue();
        return no;
    }

    public static String get获取几个字节不够补0(String str,int byteNo){
        if (byteNo == 1) {
            if (str.length() < 2) {
                str = "0" + str;
            }
        }
        else if (byteNo == 2) {
            if (str.length() < 2) {
                str = "000" + str;
            } else if (str.length() < 3) {
                str = "00" + str;
            }else if (str.length() < 4) {
                str = "0" + str;
            }
        }else if (byteNo == 4) {
            if (str.length() < 2) {
                str = "0000000" + str;
            } else if (str.length() < 3) {
                str = "000000" + str;
            }else if (str.length() < 4) {
                str = "00000" + str;
            }else if (str.length() < 5) {
                str = "0000" + str;
            }else if (str.length() < 6) {
                str = "000" + str;
            }else if (str.length() < 7) {
                str = "00" + str;
            }else if (str.length() < 8) {
                str = "0" + str;
            }
        }else if (byteNo == 5) {
            if (str.length() < 2) {
                str = "000000000" + str;
            } else if (str.length() < 3) {
                str = "00000000" + str;
            }else if (str.length() < 4) {
                str = "0000000" + str;
            }else if (str.length() < 5) {
                str = "000000" + str;
            }else if (str.length() < 6) {
                str = "00000" + str;
            }else if (str.length() < 7) {
                str = "0000" + str;
            }else if (str.length() < 8) {
                str = "000" + str;
            }else if (str.length() < 9) {
                str = "00" + str;
            }else if (str.length() < 10) {
                str = "0" + str;
            }
        }else if (byteNo == 6) {
            if (str.length() < 2) {
                str = "00000000000" + str;
            } else if (str.length() < 3) {
                str = "0000000000" + str;
            }else if (str.length() < 4) {
                str = "000000000" + str;
            }else if (str.length() < 5) {
                str = "00000000" + str;
            }else if (str.length() < 6) {
                str = "0000000" + str;
            }else if (str.length() < 7) {
                str = "000000" + str;
            }else if (str.length() < 8) {
                str = "00000" + str;
            }else if (str.length() < 9) {
                str = "0000" + str;
            }else if (str.length() < 10) {
                str = "000" + str;
            }else if (str.length() < 11) {
                str = "00" + str;
            }else if (str.length() < 12) {
                str = "0" + str;
            }
        }
        return str;
    }

    public static String get大小端序转化(String ox){
        List<String> list_1 = new ArrayList<>();
        int len = ox.length() / 2;
        for (int q = 0; q < len; q++) {
            list_1.add(ox.substring(0, 2));
            ox = ox.substring(2);
        }
        Collections.reverse(list_1);

        String cmd = "";
        for (int x = 0; x < list_1.size(); x++) {
            cmd += list_1.get(x);
        }

        return cmd;
    }

    private static String hexStr =  "0123456789ABCDEF";
    private static String[] binaryArray =
            {"0000","0001","0010","0011",
                    "0100","0101","0110","0111",
                    "1000","1001","1010","1011",
                    "1100","1101","1110","1111"};
    /**
     * @return 转换为二进制字符串
     */
    public static String zh将字节数组转成二进制字符串(byte[] bArray){
        String outStr = "";
        int pos = 0;
        for(byte b:bArray){
            //高四位
            pos = (b&0xF0)>>4;
            outStr += binaryArray[pos];
            //低四位
            pos=b&0x0F;
            outStr += binaryArray[pos];
        }
        return outStr;
    }

    /**
     * @param bytes
     * @return 将二进制转换为十六进制字符输出
     */
    public static String zh将二进制转换为十六进制字符(byte[] bytes){

        String result = "";
        String hex = "";
        for(int i=0;i<bytes.length;i++){
            //字节高4位
            hex = String.valueOf(hexStr.charAt((bytes[i]&0xF0)>>4));
            //字节低4位
            hex += String.valueOf(hexStr.charAt(bytes[i]&0x0F));
            result +=hex+" ";
        }
        return result;
    }

    /**
     * @param hexString
     * @return 将十六进制转换为字节数组
     */
    public static byte[] zh将十六进制转换为字节数组(String hexString){
        //hexString的长度对2取整，作为bytes的长度
        int len = hexString.length()/2;
        byte[] bytes = new byte[len];
        byte high = 0;//字节高四位
        byte low = 0;//字节低四位

        for(int i=0;i<len;i++){
            //右移四位得到高位
            high = (byte)((hexStr.indexOf(hexString.charAt(2*i)))<<4);
            low = (byte)hexStr.indexOf(hexString.charAt(2*i+1));
            bytes[i] = (byte) (high|low);//高地位做或运算
        }
        return bytes;
    }

    public static int zh将字节数组转成十进制(byte[] bRefArr) {
        int iOutcome = 0;
        byte bLoop;
        for (int i = 0; i < bRefArr.length; i++) {
            bLoop = bRefArr[i];
            iOutcome += (bLoop & 0xFF) << (8 * i);
        }
        return iOutcome;
    }

    /**
     * 二进制字符串转换为byte数组,每个字节以","隔开
     **/
    public static byte[] zh将二进制字符串转成字节数组(String binStr) {
        String[] temp = binStr.split(",");
        byte[] b = new byte[temp.length];
        for (int i = 0; i < b.length; i++) {
            b[i] = Long.valueOf(temp[i], 2).byteValue();
        }
        return b;
    }


    /**
     * 大小端序转化
     * */
    public static String zh大小端序转化(String ox){
        List<String> list_1 = new ArrayList<>();
        int len = ox.length() / 2;
        for (int q = 0; q < len; q++) {
            list_1.add(ox.substring(0, 2));
            ox = ox.substring(2);
        }
        Collections.reverse(list_1);

        String cmd = "";
        for (int x = 0; x < list_1.size(); x++) {
            cmd += list_1.get(x);
        }

        return cmd;
    }


    public static String to把十六进制编码为字符串_GBK(String cmd){
        String str内容 = "";
        try {
            str内容 = toStringHex2(cmd);
        } catch (Exception e) {
            str内容 = cmd;

        }
        return str内容;
    }
    public static String to把十六进制编码为字符串_UTF8(String cmd){
        String str内容 = "";
        try {
            str内容 = toStringHex2_UTF8(cmd);
        } catch (Exception e) {
            str内容 = cmd;

        }
        return str内容;
    }
    public static String to把十六进制编码为字符串_ASCII(String cmd){
        String str内容 = "";
        try {
            str内容 = parseAscii(cmd);
        } catch (Exception e) {
            str内容 = cmd;

        }
        return str内容;
    }

    public static String to把字符串GBK编码为十六进制(String cmd){
        String str内容 = "";
        try {
            ByteBuffer writeBuffer = ByteBuffer.wrap(cmd.getBytes("GBK"));
            str内容 = bytes2HexString(writeBuffer);
        } catch (Exception e) {
            str内容 = cmd;

        }
        return str内容;
    }
    public static String to把字符串UTF8编码为十六进制(String cmd){
        String str内容 = "";
        try {
            ByteBuffer writeBuffer = ByteBuffer.wrap(cmd.getBytes("UTF-8"));
            str内容 = bytes2HexString(writeBuffer);
        } catch (Exception e) {
            str内容 = cmd;

        }
        return str内容;
    }

    /*
     * 字节数组转16进制字符串
     */
    public static String bytes2HexString(byte[] array) {
        StringBuilder builder = new StringBuilder();

        for (byte b : array) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            builder.append(hex);
        }

        return builder.toString().toUpperCase();
    }
    /*16进制byte数组转String*/
    public static String bytes2HexString(ByteBuffer byteBuffer) {
        String r = "";
        byte[] b = conver(byteBuffer);
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            r += hex.toUpperCase();
        }
        return r;
    }

    private static byte[] conver(ByteBuffer byteBuffer){
        int len = byteBuffer.limit() - byteBuffer.position();
        byte[] bytes = new byte[len];

        if(byteBuffer.isReadOnly()){
            return null;
        }else {
            byteBuffer.get(bytes);
        }
        return bytes;
    }

    /**
     * 十六进制编码为字符串
     * */
    public static String toStringHex2(String s) {
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(
                        i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "GBK");// UTF-16le:Not
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }

    /**
     * 十六进制编码为字符串
     * */
    public static String toStringHex2_UTF8(String s) {
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(
                        i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "UTF-8");// UTF-16le:Not
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }

    /**
     * 字符串转ASCII码
     * @param str
     * @return
     */
    public static String parseAscii(String str){
        StringBuilder sb=new StringBuilder();
        byte[] bs=str.getBytes();
        for(int i=0;i<bs.length;i++)
            sb.append(toHex(bs[i]));
        return sb.toString();
    }

    private static String toHex(int n){
        StringBuilder sb=new StringBuilder();
        if(n/16==0){
            return toHexUtil(n);
        }else{
            String t=toHex(n/16);
            int nn=n%16;
            sb.append(t).append(toHexUtil(nn));
        }
        return sb.toString();
    }

    private static String toHexUtil(int n){
        String rt="";
        switch(n){
            case 10:rt+="A";break;
            case 11:rt+="B";break;
            case 12:rt+="C";break;
            case 13:rt+="D";break;
            case 14:rt+="E";break;
            case 15:rt+="F";break;
            default:
                rt+=n;
        }
        return rt;
    }

    public static byte[] int2ByteArray(int a) {
        return new byte[]{
                (byte) ((a >> 8) & 0xFF),
                (byte) (a & 0xFF)
        };
    }


    public static byte[] int1ByteArray(int a) {
        return new byte[]{
                (byte) (a & 0xFF)
        };
    }
}
